package com.shaohai.live;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.qiniu.android.dns.DnsManager;
import com.qiniu.android.dns.IResolver;
import com.qiniu.android.dns.NetworkInfo;
import com.qiniu.android.dns.http.DnspodFree;
import com.qiniu.android.dns.local.AndroidDnsServer;
import com.qiniu.android.dns.local.Resolver;
import com.qiniu.pili.droid.streaming.AVCodecType;
import com.qiniu.pili.droid.streaming.CameraStreamingSetting;
import com.qiniu.pili.droid.streaming.MediaStreamingManager;
import com.qiniu.pili.droid.streaming.StreamStatusCallback;
import com.qiniu.pili.droid.streaming.StreamingProfile;
import com.qiniu.pili.droid.streaming.StreamingState;
import com.qiniu.pili.droid.streaming.StreamingStateChangedListener;
import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton;
import com.shaohai.live.adapter.ChatMessageAdapter;
import com.shaohai.live.entity.Course;
import com.shaohai.live.ui.CameraPreviewFrameView;
import com.shaohai.live.ui.FSActivity;
import com.shaohai.live.ui.FSBarActivity;
import com.shaohai.live.utils.AppDefine;
import com.shaohai.live.utils.ChatMessage;
import com.shaohai.live.utils.DeviceHelper;
import com.shaohai.live.utils.StringUtils;

import java.io.IOException;
import java.net.InetAddress;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.RuntimePermissions;

@RuntimePermissions
public class LiveVideoActivity extends FSActivity implements StreamingStateChangedListener, StreamStatusCallback {
    @BindView(R.id.cameraPreview_surfaceView) CameraPreviewFrameView cameraPreviewFrameView;
    @BindView(R.id.mStatView) TextView mStatView;
    @BindView(R.id.ivStart) ImageView ivStart;
    @BindView(R.id.btnSend) QMUIRoundButton btnSend;
    @BindView(R.id.listMessage) ListView listMessage;
    @BindView(R.id.edit_content) EditText edit_content;
    private MediaStreamingManager mMediaStreamingManager;
    protected StreamingProfile mProfile = new StreamingProfile();
    private String TAG = "PUSHSTREAM";
    Course course;
    List<ChatMessage> messageList;
    ChatMessageAdapter messageAdapter;
    boolean mIsEncOrientationPort = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setRequestedOrientation(mIsEncOrientationPort ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        setContentView(R.layout.activity_live_video);
        ButterKnife.bind(this);
        initializeView();
    }

    @Override
    protected void initializeView() {
        course = (Course) getIntent().getSerializableExtra(AppDefine.TRANS_COURSE);
        if (course == null || StringUtils.isNullOrEmpty(course.pushurl)) {
            showToast("课程信息有误，请及时联系技术支持！");
            return;
        }
        LiveVideoActivityPermissionsDispatcher.startPushVideoWithPermissionCheck(LiveVideoActivity.this);
        ivStart.setOnClickListener(view -> {
            if (!isPushing) {
                startStreamingInternal();
            } else {
                mMediaStreamingManager.stopStreaming();
                isPushing = false;
                ivStart.setImageDrawable(getResources().getDrawable(R.drawable.play_start));
            }
        });
        messageList = new ArrayList<>();
        messageAdapter = new ChatMessageAdapter(context, messageList);
        listMessage.setAdapter(messageAdapter);
        btnSend.setOnClickListener(view -> {
            ChatMessage message = new ChatMessage();
            message.username = "张文彬";
            message.message = edit_content.getText().toString().trim();
            messageList.add(message);
            messageAdapter.notifyDataSetChanged();
            DeviceHelper.hideInputWindow(context, edit_content);
        });
        DeviceHelper.hideInputWindow(context, edit_content);
    }

    @NeedsPermission({Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE})
    protected void startPushVideo() {
        try {
            mProfile.setPublishUrl(StringUtils.GetPushURL());
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        initStreamingManager();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        LiveVideoActivityPermissionsDispatcher.onRequestPermissionsResult(LiveVideoActivity.this, requestCode, grantResults);
    }

    private boolean isPushing = false;

    protected void initStreamingManager() {
        mProfile.setVideoQuality(StreamingProfile.VIDEO_QUALITY_HIGH1)
                .setAudioQuality(StreamingProfile.AUDIO_QUALITY_MEDIUM2)
                .setQuicEnable(false)//RMPT or QUIC
                .setVideoQuality(StreamingProfile.VIDEO_QUALITY_MEDIUM1)
                .setEncodingOrientation(mIsEncOrientationPort ? StreamingProfile.ENCODING_ORIENTATION.PORT : StreamingProfile.ENCODING_ORIENTATION.LAND)//横竖屏
                .setEncodingSizeLevel(StreamingProfile.VIDEO_ENCODING_HEIGHT_480)
                .setBitrateAdjustMode(StreamingProfile.BitrateAdjustMode.Auto)//自适应码率
                .setEncoderRCMode(StreamingProfile.EncoderRCModes.QUALITY_PRIORITY)
                .setDnsManager(getMyDnsManager())
                .setStreamStatusConfig(new StreamingProfile.StreamStatusConfig(3))
                .setSendingBufferProfile(new StreamingProfile.SendingBufferProfile(0.2f, 0.8f, 3.0f, 20 * 1000));
        //.setPublishUrl(GetPushURL());//设置推流地址

        CameraStreamingSetting setting = new CameraStreamingSetting();
        setting.setCameraId(Camera.CameraInfo.CAMERA_FACING_FRONT) // 摄像头切换
                .setContinuousFocusModeEnabled(true)
                .setFaceBeautySetting(new CameraStreamingSetting.FaceBeautySetting(1.0f, 1.0f, 1.0f))//美颜 磨皮，美白，红润 取值范围为[0.0f, 1.0f]
                .setVideoFilter(CameraStreamingSetting.VIDEO_FILTER_TYPE.VIDEO_FILTER_BEAUTY)
                .setCameraPrvSizeLevel(CameraStreamingSetting.PREVIEW_SIZE_LEVEL.MEDIUM)
                .setCameraPrvSizeRatio(CameraStreamingSetting.PREVIEW_SIZE_RATIO.RATIO_16_9);
        mMediaStreamingManager = new MediaStreamingManager(this, cameraPreviewFrameView, AVCodecType.SW_VIDEO_WITH_SW_AUDIO_CODEC);
        mMediaStreamingManager.prepare(setting, mProfile);
        mMediaStreamingManager.setStreamingStateListener(this);
        mMediaStreamingManager.setStreamStatusCallback(this);
    }



    protected DnsManager getMyDnsManager() {
        IResolver r0 = null;
        IResolver r1 = new DnspodFree();
        IResolver r2 = AndroidDnsServer.defaultResolver();
        try {
            r0 = new Resolver(InetAddress.getByName("119.29.29.29"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return new DnsManager(NetworkInfo.normal, new IResolver[]{r0, r1, r2});
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mMediaStreamingManager != null)
            mMediaStreamingManager.resume();
    }

    protected boolean startStreaming() {
        return mMediaStreamingManager.startStreaming();
    }

    protected boolean stopStreaming() {
        return mMediaStreamingManager.stopStreaming();
    }

    @Override
    public void onStateChanged(StreamingState streamingState, Object extra) {
        /**
         * general states are handled in the `StreamingBaseActivity`
         */

        Log.i(TAG, "StreamingState streamingState:" + streamingState + ",extra:" + extra);
        switch (streamingState) {
            case READY:
                startStreamingInternal();
                break;
            case SHUTDOWN:
                startStreaming();
                break;
            case OPEN_CAMERA_FAIL:
                Log.e(TAG, "Open Camera Fail. id:" + extra);
                break;
            case CAMERA_SWITCHED:
                if (extra != null) {
                    Log.i(TAG, "current camera id:" + (Integer) extra);
                }
                Log.i(TAG, "camera switched");
                final int currentCamId = (Integer) extra;
                this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                    }
                });
                break;
            case TORCH_INFO:
                if (extra != null) {
                    final boolean isSupportedTorch = (Boolean) extra;
                    Log.i(TAG, "isSupportedTorch=" + isSupportedTorch);

                }
                break;
        }
    }

    protected void startStreamingInternal() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                boolean res = startStreaming();
                isPushing = res;
                ivStart.setImageDrawable(getResources().getDrawable(R.drawable.play_stop));
            }
        }).start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mMediaStreamingManager != null)
            mMediaStreamingManager.pause();
        ivStart.setImageDrawable(getResources().getDrawable(R.drawable.play_start));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMediaStreamingManager != null)
            mMediaStreamingManager.destroy();
    }

    @Override
    public void notifyStreamStatusChanged(final StreamingProfile.StreamStatus streamStatus) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "run:totalAVBitrate ===>" + streamStatus.totalAVBitrate);
                Log.d(TAG, "run:audioFps ===>" + streamStatus.audioFps);
                Log.d(TAG, "run:videoFps ===>" + streamStatus.videoFps);
                mStatView.setText("bitrate:" + streamStatus.totalAVBitrate / 1024 + " kbps"
                        + "\naudio:" + streamStatus.audioFps + " fps"
                        + "\nvideo:" + streamStatus.videoFps + " fps");
            }
        });
    }
}
